/*
 * @Author: liusheng
 * @Date: 2022-05-07 21:54:25
 * @LastEditors: liusheng
 * @LastEditTime: 2022-05-08 22:24:57
 * @Description: 剑指 Offer II 060. 出现频率最高的 k 个数字
 * email:liusheng613@126.com
 * Copyright (c) 2022 by liusheng/liusheng, All Rights Reserved. 
 
 剑指 Offer II 060. 出现频率最高的 k 个数字
给定一个整数数组 nums 和一个整数 k ，请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。

 

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]
 

提示：

1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一，换句话说，数组中前 k 个高频元素的集合是唯一的
 

进阶：所设计算法的时间复杂度 必须 优于 O(n log n) ，其中 n 是数组大小。

 

注意：本题与主站 347 题相同：https://leetcode-cn.com/problems/top-k-frequent-elements/

通过次数11,477 提交次数16,549
*/

#include "header.h"

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        /* hash table to record num frequent*/
        unordered_map<int,int> numFreq;
        int n = nums.size();
        for (int i = 0; i < n; ++i)
        {
            numFreq[nums[i]]++;
        }
        
        /* using pair to record freq:Num */
        using pd = pair<int,int>;
        struct pairGreaterCmp
        {
            constexpr bool operator () (const pd & a,const pd & b)
            {
                return a.first > b.first;
            }
        };
        
        priority_queue<pd,vector<pd>,pairGreaterCmp> freqNum;
        /*use little-edian heap to keep the k most freq num
         keep the heap only has k top freq freq:num pair 
        */
        for (auto num : numFreq)
        {
            if (freqNum.size() < k)
            {
                freqNum.push(make_pair(num.second,num.first));
            }
            else
            {
                //only push in queue when num freq is bigger than queue top's Freq(the kth)
                if (num.second > freqNum.top().first)
                {
                    freqNum.push(make_pair(num.second,num.first));
                    freqNum.pop();
                }
            }
        }
        
        
        vector<int> topK(freqNum.size());
        for (int i = 0; i < k; ++i)
        {
            topK[k-1-i] = freqNum.top().second;
            freqNum.pop();
        }
        
        return topK;
    }
};